import { _decorator, Animation, AnimationClip } from 'cc'
import { ENTITY_STATE_ENUM, PARAMS_NAME_ENUM } from '../../Enum'
import { PlayerManager } from '../PlayerManager'
import { StateMachine } from '../../Base/StateMachine'
import { IdleState } from './IdleState'
import { RunState } from './RunState'
import { JumpState } from './JumpState'
import { FallState } from './FallState'
import { SlideState } from './SlideState'
import { DashState } from './DashState'
import EventManager from '../../Base/EventManager'
import { WallJumpState } from './WallJumpState'
import { Coroutine } from './Coroutine'
import { SuperJumpState } from './SuperJumpState'
import { SuperWallJumpState } from './SuperWallJumpState'
const { ccclass, property } = _decorator

@ccclass('PlayerStateMachine')
export class PlayerStateMachine extends StateMachine<ENTITY_STATE_ENUM> {
    player: PlayerManager

    // State parameters
    isFacingRight: boolean = true;

    // Timers
    lastOnGroundTime: number = 0;
    lastOnWallTime: number = 0;
    lastOnWallRightTime: number = 0;
    lastOnWallLeftTime: number = 0;
    lastPressedJumpTime: number = 0;
    lastPressedDashTime: number = 0;

    dashAmount: number = 1;
    dashRefilling: boolean = false;

    coroutine: Coroutine = new Coroutine();

    protected onLoad(): void {
        EventManager.Instance.on(PARAMS_NAME_ENUM.JUMP, this.onJumpInput, this)
        EventManager.Instance.on(PARAMS_NAME_ENUM.DASH, this.onDashInput, this)
    }
    protected onDestroy(): void {
        EventManager.Instance.off(PARAMS_NAME_ENUM.JUMP, this.onJumpInput)
        EventManager.Instance.off(PARAMS_NAME_ENUM.DASH, this.onDashInput)
    }
    protected start(): void {
        this.init(this.player)
    }
    async init(_player: PlayerManager) {
        this.player = _player
        this.animationComponent = this.node.addComponent(Animation)

        this.registerState()

        await Promise.all(this.waitingList)
        console.log('所有资源加载完毕')
        this.startWith(ENTITY_STATE_ENUM.IDLE)

        this.isFacingRight = true;
        this.setGravityScale(this.player.data.gravityScale);
    }

    startWith(name: ENTITY_STATE_ENUM) {
        console.log('状态机开始运行')
        this.defaultState = name;
        this.mainMachine.transitTo(name);
    }

    updateTimers(dt: number) {
        this.lastOnGroundTime -= dt;
        this.lastOnWallTime -= dt;
        this.lastOnWallRightTime -= dt;
        this.lastOnWallLeftTime -= dt;
        this.lastPressedJumpTime -= dt;
        this.lastPressedDashTime -= dt;
    }

    update(dt: number): void {
        if(!this.defaultState)return;
        this.updateTimers(dt);

        super.update(dt);
        if (this.coroutine.active) {
            this.coroutine.update(dt);
        }
    }

    registerState() {
        this.mainMachine.add(new IdleState(ENTITY_STATE_ENUM.IDLE, ENTITY_STATE_ENUM.IDLE, this, "texture/player/idle", AnimationClip.WrapMode.Loop))
        this.mainMachine.add(new RunState(ENTITY_STATE_ENUM.RUN, ENTITY_STATE_ENUM.RUN, this, "texture/player/run", AnimationClip.WrapMode.Loop))
        this.mainMachine.add(new JumpState(ENTITY_STATE_ENUM.JUMP, ENTITY_STATE_ENUM.JUMP, this, "texture/player/jump", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new WallJumpState(ENTITY_STATE_ENUM.WALL_JUMP, ENTITY_STATE_ENUM.JUMP, this, "texture/player/jump", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new FallState(ENTITY_STATE_ENUM.FALL, ENTITY_STATE_ENUM.FALL, this, "texture/player/fall", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new SlideState(ENTITY_STATE_ENUM.SLIDE, ENTITY_STATE_ENUM.SLIDE, this, "texture/player/slide", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new DashState(ENTITY_STATE_ENUM.DASH, ENTITY_STATE_ENUM.DASH, this, "texture/player/dash", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new SuperJumpState(ENTITY_STATE_ENUM.SUPER_JUMP, ENTITY_STATE_ENUM.JUMP, this, "texture/player/jump", AnimationClip.WrapMode.Normal))
        this.mainMachine.add(new SuperWallJumpState(ENTITY_STATE_ENUM.SUPER_WALL_JUMP, ENTITY_STATE_ENUM.JUMP, this, "texture/player/jump", AnimationClip.WrapMode.Normal))
    }

    public setGravityScale(scale: number) {
        this.player.rb.gravityScale = scale;
    }

    public onJumpInput() {
        this.lastPressedJumpTime = this.player.data.jumpInputBufferTime;
    }

    public onDashInput() {
        this.lastPressedDashTime = this.player.data.dashInputBufferTime;
    }

}


